<template>
  <div class="back">
    <canvas ref="particlesCanvas"></canvas>
    <canvas ref="fireworksCanvas"></canvas>
    <router-view />
  </div>
</template>

<script>
export default {
  name: "App",
  mounted() {
    this.initParticles();
    this.initFireworks();
  },
  beforeUnmount() {
    cancelAnimationFrame(this.particlesAnimationFrameId);
    cancelAnimationFrame(this.fireworksAnimationFrameId);
  },
  methods: {
    // 粒子拖尾效果
    initParticles() {
      const canvas = this.$refs.particlesCanvas;
      const c = canvas.getContext("2d");

      // 设置 canvas 尺寸
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;

      // 鼠标位置
      let mouse = {
        x: window.innerWidth / 2,
        y: window.innerHeight / 2,
      };

      // 粒子拖尾参数
      const particlesParams = {
        particleCount: 100, // 粒子数量
        minRadius: 1, // 粒子最小半径
        maxRadius: 4, // 粒子最大半径
        fadeSpeed: 0.005, // 粒子消失速度
        minDistance: 50, // 粒子最小距离
        maxDistance: 120, // 粒子最大距离
        colorArray: [ // 粒子颜色数组
          "#FFE4E1", /* 浅粉红 */
          "#FFDAB9", /* 桃橙色 */
          "#FFC0CB", /* 粉红色 */
          "#FFB6C1", /* 亮粉红 */
          "#FFA07A", /* 浅橙红 */
          "#FF8C69", /* 鲑鱼红 */
          "#FF7F50", /* 珊瑚色 */
          "#FF6B6B", /* 亮珊瑚红 */
          "#FF6347", /* 番茄红 */
          "#FF4500"  /* 橙红色 */
        ]
      };

      // 粒子类
      class Particle {
        constructor(x, y) {
          this.x = x;
          this.y = y;
          this.radius = Math.random() * (particlesParams.maxRadius - particlesParams.minRadius) + particlesParams.minRadius;
          this.color = particlesParams.colorArray[Math.floor(Math.random() * particlesParams.colorArray.length)];
          this.radians = Math.random() * Math.PI * 2;
          this.velocity = 0.05;
          this.distanceFromCenter = {
            x: Math.random() * (particlesParams.maxDistance - particlesParams.minDistance) + particlesParams.minDistance,
            y: Math.random() * (particlesParams.maxDistance - particlesParams.minDistance) + particlesParams.minDistance,
          };
          this.lastMouse = { x: x, y: y };
          this.opacity = 1; // 透明度
        }

        update() {
          this.radians += this.velocity;

          // 拖尾效果
          this.lastMouse.x += (mouse.x - this.lastMouse.x) * 0.1;
          this.lastMouse.y += (mouse.y - this.lastMouse.y) * 0.1;

          // 圆形运动
          this.x =
              this.lastMouse.x +
              Math.cos(this.radians) * this.distanceFromCenter.x;
          this.y =
              this.lastMouse.y +
              Math.sin(this.radians) * this.distanceFromCenter.y;

          // 透明度逐渐降低
          this.opacity -= particlesParams.fadeSpeed;

          this.draw();
        }

        draw() {
          c.beginPath();
          c.fillStyle = `${this.color}${Math.floor(this.opacity * 255).toString(16).padStart(2, '0')}`;
          c.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
          c.fill();
          c.closePath();
        }

        shouldRemove() {
          return this.opacity <= 0;
        }
      }

      // 粒子数组
      let particles = [];

      // 初始化粒子
      function init() {
        particles = [];
        for (let i = 0; i < particlesParams.particleCount; i++) {
          particles.push(
              new Particle(
                  window.innerWidth / 2,
                  window.innerHeight / 2
              )
          );
        }
      }

      // 动画循环
      this.particlesAnimationFrameId = null;
      function animate() {
        this.particlesAnimationFrameId = requestAnimationFrame(animate.bind(this));

        // 清除画布
        c.clearRect(0, 0, window.innerWidth, window.innerHeight);

        // 绘制粒子
        particles.forEach((particle, index) => {
          particle.update();

          // 移除透明度过低的粒子
          if (particle.shouldRemove()) {
            particles.splice(index, 1);
          }
        });

        // 添加新粒子
        if (Math.random() <100) {//定义生成速度
          particles.push(
              new Particle(
                  mouse.x,
                  mouse.y
              )
          );
        }
      }

      // 事件监听
      window.addEventListener("mousemove", (event) => {
        mouse.x = event.clientX;
        mouse.y = event.clientY;
      });

      window.addEventListener("resize", () => {
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        init();
      });

      init();
      animate.call(this);
    },

    // 烟花效果
    initFireworks() {
      const canvas = this.$refs.fireworksCanvas;
      const c = canvas.getContext("2d");

      // 设置 canvas 尺寸
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;

      // 烟花参数
      const fireworksParams = {
        minBalls: 50, // 最小烟花数量
        maxBalls: 100, // 最大烟花数量
        minRadius: 2, // 最小半径
        maxRadius: 6, // 最大半径
        fadeSpeed: 0.15 , // 烟花消失速度
        colorArray: [ // 烟花颜色数组
          "#FFB347", /* 亮橙色 */
          "#FF8C42", /* 深橙色 */
          "#FF6961", /* 亮珊瑚红 */
          "#FF6B6B", /* 亮粉红 */
          "#FF77FF", /* 亮紫粉 */
          "#FF85FF", /* 浅紫粉 */
          "#FFA07A", /* 浅橙红 */
          "#FFB6C1", /* 亮粉红 */
          "#FFC0CB", /* 粉红色 */
          "#FFD700"  /* 金色 */
        ]
      };

      // 烟花类
      class Ball {
        constructor(x, y) {
          this.x = x;
          this.y = y;
          this.angle = Math.PI * 2 * Math.random();
          this.multiplier = Math.random() * 6 + 6;
          this.vx = (this.multiplier + Math.random() * 0.5) * Math.cos(this.angle);
          this.vy = (this.multiplier + Math.random() * 0.5) * Math.sin(this.angle);
          this.r = Math.random() * (fireworksParams.maxRadius - fireworksParams.minRadius) + fireworksParams.minRadius;
          this.color = fireworksParams.colorArray[Math.floor(Math.random() * fireworksParams.colorArray.length)];
        }

        update() {
          this.x += this.vx;
          this.y += this.vy;
          this.r -= fireworksParams.fadeSpeed;
          this.vx *= 0.9;
          this.vy *= 0.9;
        }
      }

      // 烟花数组
      let balls = [];

      // 推送烟花
      function pushBalls(x, y) {
        const count = Math.floor(Math.random() * (fireworksParams.maxBalls - fireworksParams.minBalls)) + fireworksParams.minBalls;
        for (let i = 0; i < count; i++) {
          balls.push(new Ball(x, y));
        }
      }

      // 动画循环
      this.fireworksAnimationFrameId = null;
      function animate() {
        this.fireworksAnimationFrameId = requestAnimationFrame(animate.bind(this));

        // 清除画布
        c.fillStyle = "rgba(255, 255, 255, 0)";
        c.clearRect(0, 0, canvas.width, canvas.height);

        // 绘制烟花
        for (let i = 0; i < balls.length; i++) {
          let b = balls[i];
          if (b.r < 0) continue;
          c.fillStyle = b.color;
          c.beginPath();
          c.arc(b.x, b.y, b.r, 0, Math.PI * 2, false);
          c.fill();
          b.update();
        }

        // 移除消失的烟花
        balls = balls.filter((b) => b.r > 0);
      }

      // 事件监听
      window.addEventListener("mousedown", (e) => {
        pushBalls(e.clientX, e.clientY);
      });

      window.addEventListener("resize", () => {
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
      });

      animate.call(this);
    },
  },
};
</script>

<style>
.back {
  height: 100vh;
  background-image: url("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fnimg.ws.126.net%2F%3Furl%3Dhttp%253A%252F%252Fdingyue.ws.126.net%252F2021%252F0627%252F790e81c6j00qvbyrj0015c000n100h2c.jpg%26thumbnail%3D650x2147483647%26quality%3D80%26type%3Djpg&refer=http%3A%2F%2Fnimg.ws.126.net&app=2002&size=f9999");
  background-size: cover;
  background-position: center;
  background-attachment: fixed;
  position: relative;
  overflow: hidden;
}

/* 确保 canvas 覆盖整个背景，但不会遮挡内容 */
canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* 粒子 canvas */
#particlesCanvas {
  z-index: 1;
}

/* 烟花 canvas */
#fireworksCanvas {
  z-index: 2;
}

.login-container {
  border-radius: 15px;
  background-clip: padding-box;
  margin: auto auto;
  width: 350px;
  padding: 35px 35px 15px 35px;
  background: #fff;
  border: 1px solid #eaeaea;
  box-shadow: 0 0 25px #cac6c6;
  position: relative;
  z-index: 3;
}

.login_title {
  margin: 0px auto 40px auto;
  text-align: center;
  color: #505458;
}

.login_remember {
  margin: 0px 0px 35px 0px;
  text-align: left;
}
</style>